package com.teamtwoseven.todo;

import java.util.regex.Pattern;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.text.method.PasswordTransformationMethod;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.AdapterView.OnItemSelectedListener;

/**
 * This screen lets the logged-in user change their password.
 * 
 * @author teamtwoseven
 */
public class ChangePassword extends Activity implements OnClickListener {
	
	private long userRowID;
	private Storage storage;
	private Button bSave, bCancel, bLogout, bDeleteAccount;
	private TextView tvCurrent, tvNew, tvInfo;
	private EditText etCurrent, etNew, etConfirm;
	private Spinner spinner;
	private int selection;

	/**
	 * Called when the activity is first created.
	 * 
	 * @param savedInstanceState
	 * 			allows instance data to be stored
	 */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.change_password);

		getUser(); // sets userRowID, storage, and the welcome text

		bSave = (Button) findViewById(R.id.changePassword_bSave);
		bCancel = (Button) findViewById(R.id.changePassword_bCancel);
		bLogout = (Button) findViewById(R.id.changePassword_bLogout);
		bDeleteAccount = (Button) findViewById(R.id.changePassword_bDeleteAccount);
		tvInfo = (TextView) findViewById(R.id.changePassword_tvInfo);
		tvCurrent = (TextView) findViewById(R.id.changePassword_tvCurrent);
		tvNew = (TextView) findViewById(R.id.changePassword_tvNew);
		etCurrent = (EditText) findViewById(R.id.changePassword_etCurrent);
		etNew = (EditText) findViewById(R.id.changePassword_etNew);
		etConfirm = (EditText) findViewById(R.id.changePassword_etConfirm);

		bSave.setOnClickListener(this);
		bCancel.setOnClickListener(this);
		bLogout.setOnClickListener(this);
		bDeleteAccount.setOnClickListener(this);
		
		spinner = (Spinner) findViewById(R.id.changePassword_spinner);
		ArrayAdapter<CharSequence> adapter =
			ArrayAdapter.createFromResource(this, R.array.settings,
			android.R.layout.simple_spinner_item);
		adapter.setDropDownViewResource(
			android.R.layout.simple_spinner_dropdown_item);
		spinner.setAdapter(adapter);
		spinner.setOnItemSelectedListener(new SpinnerListener());
		selection = 0;
		spinner.setSelection(selection); // selects "Password"
	}

	/**
	 * Handles button clicks
	 * 
	 * @param arg0
	 * 			the element that was clicked
	 */
	public void onClick(View arg0) {
		if (arg0 == bSave) {
			String current = etCurrent.getText().toString();
			String next = etNew.getText().toString();
			String confirm = etConfirm.getText().toString();

			switch (selection) {
			case 1: // "Change Email"
				// If the emails are valid, change the stored email, end this
				// Activity, and return to Main
				if (verifyEmail(current, next, confirm)) {
					storage.changeEmail(userRowID, next);
					
					popupDialog("Your email address has been changed", true);
				}
				break;
			case 2: // "Change Name"
				// If the names are valid, change the stored name, end this
				// Activity, and return to Main
				if (verifyName(current, next, confirm)) {
					storage.changeFullName(userRowID, next);
					
					getUser(); // updates the welcome text with the new name
					setResult(3); // tells Main to update its welcome text
					popupDialog("Your name has been changed", true);
				}
				break;
			default: // "Change Password"
				// If the passwords are valid, change the stored password, end
				// this Activity, and return to Main
				if (verifyPW(current, next, confirm)) {
					storage.changePassword(userRowID, next);
					
					popupDialog("Your password has been changed", true);
				}
				break;
			}
		}
		else if (arg0 == bCancel) {
			// End this Activity and return to Main
			finish();
		}
		else if (arg0 == bLogout) {
			// End this Activity; Main will launch the login screen
			setResult(1);
			finish();
		}
		else if (arg0 == bDeleteAccount) {
			// Delete this account, then logout
			storage.deleteUser(userRowID);
			setResult(1);
			finish();
		}
	}

	/**
	 * Verifies the given passwords are valid. If not, displays a dialog
	 * listing why.
	 * 
	 * @param currentPW
	 * 			the current password
	 * @param newPW
	 * 			a new password
	 * @param confirmPW
	 * 			the new password, again
	 * @return true if all passwords are valid, false if at least one is not
	 */
	private boolean verifyPW(String currentPW, String newPW, String confirmPW) {
		boolean success = true;
		String feedback = "";

		if (currentPW.length() < 1) {
			feedback += "Enter your current password\n";
			success = false;
		}
		if (newPW.length() < 6) {
			feedback += "New password must be at least 6 characters\n";
			success = false;
		}
		if (!newPW.equals(confirmPW)) {
			feedback += "Confirmation password does not match new password";
			success = false;
		}
		if (success) {
			String storedPW = storage.getPassword(userRowID);
			
			if (!currentPW.equals(storedPW)) {
				feedback += "The current password you entered is incorrect\n";
				success = false;
			}
		}
		if (!success) {
			// Display which parameters are invalid
			popupDialog(feedback, false);
		}
		return success;
	}
	
	private boolean verifyName(String current, String next, String confirm) {
		boolean success = true;
		String feedback = "";

		if (current.replaceAll("\\s+", "").equals("")) {
			feedback += "Enter your current name\n";
			success = false;
		}
		if (next.replaceAll("\\s+", "").equals("")) {
			feedback += "Enter a new name\n";
			success = false;
		}
		if (!next.equals(confirm)) {
			feedback += "Confirmation name does not match new name";
			success = false;
		}
		if (success) {
			String storedName = storage.getFullName(userRowID);
			
			if (!current.equals(storedName)) {
				feedback += "The current name you entered is incorrect\n";
				success = false;
			}
		}
		if (!success) {
			// Display which parameters are invalid
			popupDialog(feedback, false);
		}
		return success;
	}

	private boolean verifyEmail(String current, String next, String confirm) {
		boolean success = true;
		String feedback = "";

		if (!validEmail(current)) {
			feedback += "Invalid Email Address\n";
			success = false;
		}
		if (!validEmail(next)) {
			feedback += "Invalid Email Address\n";
			success = false;
		}
		if (!next.equals(confirm)) {
			feedback += "Confirmation email does not match new email";
			success = false;
		}
		if (success) {
			String storedEmail = storage.getEmail(userRowID);
			
			if (!current.equals(storedEmail)) {
				feedback += "The current email you entered is incorrect\n";
				success = false;
			}
		}
		if (!success) {
			// Display which parameters are invalid
			popupDialog(feedback, false);
		}
		return success;
	}
	
	/**
	 * Validates the given email address.
	 * 
	 * @param email
	 * 			the email address in question
	 * @return true if the email address is valid, false if not
	 */
	public boolean validEmail(String email) {		
		return Pattern.compile("^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@" +
			"[A-Za-z0-9]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$").matcher(
			email).matches();
	}

	/**
	 * Displays a dialog listing the given message and an OK button. If done is
	 * true, clicking OK ends this Activity. Otherwise OK closes the dialog.
	 * 
	 * @param message
	 * 			text to display to the user
	 * @param done
	 * 			if true, clicking OK finishes the Activity; if false, OK just
	 * 			closes the dialog
	 */
	private void popupDialog(String message, final boolean done) {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);

		builder.setMessage(message);
		builder.setCancelable(false);
		builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int id) {
				dialog.cancel();
				if (done) {
					finish();
				}
			}
		});
		builder.show();
	}

	/**
	 * Gets the row ID of the current user's stored info. Also sets the welcome
	 * text to display the user's full name if it is less than 22 characters;
	 * up to 22 characters of the user's first name otherwise.
	 */
	private void getUser() {
		userRowID = Singleton.getInstance().getUserRowID();
		storage = new Storage(ChangePassword.this);
		
		String name = storage.getFullName(userRowID);

		if (name.length() > 22) {
			name = name.substring(0, 22);
			if (name.substring(1, 21).contains(" ")) {
				name = name.substring(0, name.indexOf(" "));
			}
		}

		TextView tvWelcome =
			(TextView) findViewById(R.id.changePassword_tvWelcome);
		tvWelcome.setText("Welcome, " + name + "!");
	}
	
	private class SpinnerListener implements OnItemSelectedListener {

		public void onItemSelected(AdapterView<?> parent, View view, int pos,
			long id) {
			
			switch (selection = pos) {
			case 1: // "Change Email"
				tvInfo.setText(
					"Touch Change Email to change a different setting");
				tvCurrent.setText("Old Email:  ");
				tvNew.setText("New Email:  ");
				etCurrent.setTransformationMethod(null);
				etNew.setTransformationMethod(null);
				etConfirm.setTransformationMethod(null);
				break;
			case 2: // "Change Name"
				tvInfo.setText(
					"Touch Change Name to change a different setting");
				tvCurrent.setText("Old Name:  ");
				tvNew.setText("New Name:  ");
				etCurrent.setTransformationMethod(null);
				etNew.setTransformationMethod(null);
				etConfirm.setTransformationMethod(null);
				break;
			default: // "Change Password"
				tvInfo.setText(
					"Touch Change Password to change a different setting");
				tvCurrent.setText("Old Password:  ");
				tvNew.setText("New Password:  ");
				etCurrent.setTransformationMethod(
					new PasswordTransformationMethod());
				etNew.setTransformationMethod(
					new PasswordTransformationMethod());
				etConfirm.setTransformationMethod(
					new PasswordTransformationMethod());
				break;
			}
		}

		/**
		 * Determines what to do when nothing on the spinner menu is selected.
		 * 
		 * @param parent
		 * 			the category menu
		 */
		@SuppressWarnings("rawtypes")
		public void onNothingSelected(AdapterView parent) {
			// Do nothing.
		}
	}
}